const path = require("path");
const fs = require("fs");
const requireDir = require("require-dir");
const Router = require("koa-router");

module.exports = class Route {
  constructor(options) {
    let { appPrefix, routeDir, mysqlInstance, redisInstance } = options || {};
    this.appPrefix = appPrefix || "";
    this.mysql = mysqlInstance;
    this.redis = redisInstance;

    if (!fs.existsSync(routeDir)) {
      throw new Error("路由文件夹需要创建,可参考npm文档");
    }
    this.routes = requireDir(routeDir);
  }

  loadRoutes() {
    const { routes, appPrefix, mysql, redis } = this;
    //路由中间件集合
    const middlewares = [];
    for (let [name, routers] of Object.entries(routes)) {
      const router = new Router({
        prefix: `${appPrefix}/${name}`,
      });
      for (let { path, method = "get", service, control } of routers) {
        //方法未定义警告
        if (!service) {
          console.warn(
            `path:${path} =>method:${method} =>service:${service}未定义！！！`
          );
          service = {
            code: 404,
          };
        }
        router[method.toLowerCase()](path, async (ctx, next) => {
          //权限校验
          const { userIds, roles, auths } = control || {};
          const { userId, roles: curRoles = [], auths: curAuths = [] } =
            ctx.control || {};
          if (userIds) {
            let userInx = userIds.indexOf(userId);
            if (userInx === -1) {
              ctx.body = {
                code: 403,
              };
            }
          }
          if (roles) {
            const crossRoles = roles.filter(function (r) {
              return curRoles.indexOf(r) > -1;
            });
            if (!crossRoles.length) {
              ctx.body = {
                code: 403,
              };
            }
          }
          if (auths) {
            const crossAuths = auths.filter(function (a) {
              return curAuths.indexOf(a) > -1;
            });
            if (!crossAuths.length) {
              ctx.body = {
                code: 403,
              };
            }
          }
          if (ctx.body && ctx.body.code === 403) {
            return;
          }
          const result = await service(ctx, { next, mysql, redis });
          ctx.body = result;
        });
      }
      console.log("route:", router.opts.prefix);
      middlewares.push(router.routes());
    }
    return middlewares;
  }

  loadUnAuths() {
    const unAuths = [];
    for (let [name, routers] of Object.entries(this.routes)) {
      for (let { path, unAuth } of routers) {
        if (unAuth) {
          unAuths.push(`${this.appPrefix}/${name}${path !== "/" ? path : ""}`);
        }
      }
    }
    return unAuths;
  }
};
